package org.depsea.oss.config.tenant;

import io.minio.BucketExistsArgs;
import io.minio.MakeBucketArgs;
import io.minio.MinioClient;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import org.depsea.oss.client.CustomerBucketOssTemplate;
import org.depsea.oss.client.OssTemplate;
import org.depsea.oss.client.OssType;
import org.depsea.oss.client.PresignedUrlGenerator;
import org.depsea.oss.client.minio.MinioCustomerBucketOssTemplate;
import org.depsea.oss.client.minio.MinioOssTemplate;
import org.depsea.oss.client.minio.MinioPresignedUrlGenerator;
import org.depsea.oss.exception.OssException;
import org.depsea.oss.filter.FileUploadFilter;
import org.depsea.oss.model.OssConfigParser;
import org.depsea.oss.strategy.FilenameHandleStrategy;
import org.springframework.context.ApplicationContext;

import java.io.IOException;
import java.util.List;
import java.util.Map;

@Slf4j
public class MinioTenantOssConfiguration extends AbstractTenantConfiguration implements TenantOssConfiguration {

    private final OssConfigParser ossConfigParser;

    private MinioClient minioClient;

    @Getter
    private OssTemplate ossTemplate;

    @Getter
    private CustomerBucketOssTemplate customerBucketOssTemplate;

    @Getter
    private PresignedUrlGenerator presignedUrlGenerator;

    public MinioTenantOssConfiguration(Map<String, String> config, ApplicationContext applicationContext) {
        super(applicationContext);
        this.ossConfigParser = new OssConfigParser(config);;
        this.init();
    }

    private void init() {
        this.minioClient = this.createClient(this.ossConfigParser);

        FilenameHandleStrategy filenameHandleStrategy = this.getFilenameHandleStrategy();
        List<FileUploadFilter> uploadFilters = this.getFilterList();

        createOssTemplate(this.minioClient, filenameHandleStrategy, uploadFilters);
        createCustomerBucketOssTemplate(this.minioClient, filenameHandleStrategy, uploadFilters);
        this.createPresignedUrlGenerator(this.minioClient);
    }

    @Override
    public OssType getOssType() {
        return OssType.MINIO;
    }

    private MinioClient createClient(OssConfigParser ossConfigParser) {
        MinioClient minioClient = MinioClient.builder()
                .endpoint(ossConfigParser.getEndpoint())
                .credentials(ossConfigParser.getAccessKey(), ossConfigParser.getSecretKey())
                .build();
        // 创建默认Bucket
        try {
            BucketExistsArgs bucketExistsArgs = BucketExistsArgs.builder()
                    .bucket(ossConfigParser.getDefaultBucketName())
                    .build();
            if (!minioClient.bucketExists(bucketExistsArgs)) {
                minioClient.makeBucket(
                        MakeBucketArgs.builder()
                                .bucket(ossConfigParser.getDefaultBucketName())
                                .build()
                );
            }
        } catch (Exception e) {
            throw new OssException("无法创建默认Bucket");
        }
        return minioClient;
    }

    private void createOssTemplate(MinioClient minioClient, FilenameHandleStrategy filenameHandleStrategy, List<FileUploadFilter> uploadFilters) {

        MinioOssTemplate minioOssTemplate = new MinioOssTemplate(minioClient, this.ossConfigParser.getDefaultBucketName());
        if (filenameHandleStrategy != null) {
            minioOssTemplate.setFilenameHandleStrategy(this.getFilenameHandleStrategy());
        }
        minioOssTemplate.addFilters(uploadFilters);
        this.ossTemplate = minioOssTemplate;
    }

    private void createCustomerBucketOssTemplate(MinioClient minioClient, FilenameHandleStrategy filenameHandleStrategy, List<FileUploadFilter> uploadFilters) {

        MinioCustomerBucketOssTemplate minioCustomerBucketOssTemplate = new MinioCustomerBucketOssTemplate(minioClient);
        if (filenameHandleStrategy != null) {
            minioCustomerBucketOssTemplate.setFilenameHandleStrategy(this.getFilenameHandleStrategy());
        }
        minioCustomerBucketOssTemplate.addFilters(uploadFilters);
        this.customerBucketOssTemplate = minioCustomerBucketOssTemplate;
    }

    private void createPresignedUrlGenerator(MinioClient minioClient) {
        this.presignedUrlGenerator = new MinioPresignedUrlGenerator(minioClient, this.ossConfigParser.getDefaultBucketName());
    }

    @Override
    public void close() throws IOException {
        try {
            this.minioClient.close();
        } catch (Exception e) {
            log.error("Could not close minio client", e);
        }
    }
}
